﻿

#include "OccWidget.hpp"


NAMESPACE_BEGIN(NSPOccWidget)


OccWidget::OccWidget(QWidget* parent) :
    QWidget(parent),
    AIS_ViewController(),
    _VIEW_MODE(VIEW_3D)
{
    /*初始化选择框*/
    this->setFont(QFont("Microsoft YaHei", 9));
    /*初始化*/
    SetAllowRotation(Standard_True);
    //m_view->ChangeRenderingParams().Method = Graphic3d_RM_RAYTRACING;


    if (m_context.IsNull()) {
        //此对象提供与X server的连接，在Windows和Mac OS中不起作用
        Handle(Aspect_DisplayConnection) m_display_connection = new Aspect_DisplayConnection();
        //创建OpenGl图形驱动
        if (m_graphic_driver.IsNull()) {
            m_graphic_driver = new OpenGl_GraphicDriver(m_display_connection);
        }
        //获取QWidget的窗口系统标识符
        WId window_handle = (WId)winId();
        // 创建Windows NT 窗口
        Handle(WNT_Window) wind = new WNT_Window((Aspect_Handle)window_handle);
        //创建3D查看器
        m_viewer = new V3d_Viewer(m_graphic_driver);
        //创建视图
        m_view = m_viewer->CreateView();
        m_view->SetWindow(wind);
        //打开窗口
        if (!wind->IsMapped()) {
            wind->Map();
        }
        //创建交互式上下文
        m_context = new AIS_InteractiveContext(m_viewer);
        m_context->DefaultDrawer()->SetFaceBoundaryDraw(Standard_True);
        //设置查看器的光照
        m_viewer->SetDefaultLights();
        //Handle(V3d_PositionalLight) aPositionalLight =
        //    new V3d_PositionalLight(gp_Pnt(0.0, -100.0, 5.0), Quantity_NOC_GREEN);
        //aPositionalLight->SetAttenuation(1, 0);
        //m_view->SetLightOn(aPositionalLight);

        //打开背景灯光
        m_viewer->SetLightOn();
        //设置视图的背景颜色为黑色
        m_view->SetBackgroundColor(Quantity_NOC_BLACK);
        /*显示直角坐标系，可以配置在窗口显示位置、文字颜色、大小、样式*/
        m_view->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_BLACK, 0.12, V3d_WIREFRAME);
        /*通过提供颜色和填充方法(默认为水平)来定义视图的渐变背景色*/
        m_view->SetBgGradientColors(Quantity_NOC_GRAY, Quantity_NOC_WHITE, Aspect_GFM_VER);
        m_view->MustBeResized();
        /*建模测试*/
        /*
        TopoDS_Shape box = BRepPrimAPI_MakeBox(1.0,1.0,1.0).Shape();
        Handle(AIS_Shape) aix_box = new AIS_Shape(box);
       Quantity_Color color = Quantity_Color(0.3, 0.5, 0.3, Quantity_TOC_RGB);
        m_context->SetMaterial(aix_box, Graphic3d_NameOfMaterial_Stone, Standard_False);
        m_context->SetColor(aix_box, color, Standard_False);
        m_context->Display(aix_box, 1,1,Standard_True);*/

        /*建立视角立方体*/
        Handle(AIS_ViewCube) H_AisViewCube = Create_AIS_ViewCube();
        m_context->Display(H_AisViewCube, Standard_True);
        /*显示文字*/
        Handle(AIS_TextLabel) H_Label = Create_AIS_2DLabel("Origin.");
        m_context->Display(H_Label, Standard_True);

        /*显示基准面*/
        this->Create_AIS_Datum();



        /* 设置交互式上下文的显示模式*/
        m_context->SetDisplayMode(AIS_Shaded, Standard_True);
        /*
        设置模型高亮风格
        颜色显示方式
        设置高亮颜色
        整体高亮
        设置透明度
        */
        //m_context->HighlightStyle(Prs3d_TypeOfHighlight_LocalDynamic)->SetColor(Quantity_NameOfColor::Quantity_NOC_BLUE);
        //m_context->HighlightStyle(Prs3d_TypeOfHighlight_LocalDynamic)->SetMethod(Aspect_TOHM_COLOR);
        //m_context->HighlightStyle(Prs3d_TypeOfHighlight_LocalDynamic)->SetDisplayMode(-1);
        //m_context->HighlightStyle(Prs3d_TypeOfHighlight_LocalDynamic)->SetTransparency(0.f);
        /*
        设置选择模型的风格
        获取选择风格
        颜色显示方式
        设置选择后颜色
        整体高亮
        设置透明度
        */
        //m_context->SelectionStyle()->SetColor(Quantity_NameOfColor::Quantity_NOC_BLUE);
        //m_context->SelectionStyle()->SetMethod(Aspect_TOHM_COLOR);
        //m_context->SelectionStyle()->SetDisplayMode(-1);
        //m_context->SelectionStyle()->SetTransparency(0.f);
    }
    //setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_NoSystemBackground);
    setBackgroundRole(QPalette::NoRole);
    setFocusPolicy(Qt::StrongFocus);
    setMouseTracking(true);

    m_viewer->Redraw();
    m_view->FitAll();


    //初始化选择框
    m_selection_rect = new AIS_RubberBand();
    m_selection_rect->SetLineType(Aspect_TOL_DASH); // 设置线条类型为实线  
    m_selection_rect->SetLineColor(Quantity_NOC_BLACK); // 设置线条颜色为黑色

}



Handle(AIS_TextLabel) OccWidget::Create_AIS_2DLabel(Standard_CString _str) {

    TCollection_ExtendedString tostr;
    Resource_Unicode::ConvertGBToUnicode(_str, tostr);
    Handle(AIS_TextLabel) a_Label = new AIS_TextLabel();
    a_Label->SetPosition(gp_Pnt(0, 0, 0)); // 设置文本位置
    a_Label->SetText(tostr);
    a_Label->SetColor(Quantity_NOC_RED);
    a_Label->SetFont("Microsoft YaHei");//一定要设置合适的字体，不然不能实现功能
    /*显示点*/

    return a_Label;
}




void OccWidget::Create_AIS_Datum() {
    ///*绘制基准面*/
    Handle(Geom_Plane) planeXY = new Geom_Plane(gp_Pln(gp::XOY()));
    Handle(AIS_Plane) aisPlaneXY = new AIS_Plane(planeXY);
    aisPlaneXY->SetTransformPersistence(new Graphic3d_TransformPers(Graphic3d_TMF_ZoomPers, gp_Pnt(0, 0, 0)));
    aisPlaneXY->SetZLayer(Graphic3d_ZLayerId_Topmost);
    aisPlaneXY->SetDisplayMode(0);
    m_context->Display(aisPlaneXY, Standard_False);

    Handle(Geom_Plane) planeXZ = new Geom_Plane(gp_Pln(gp::ZOX()));
    Handle(AIS_Plane) aisPlaneXZ = new AIS_Plane(planeXZ);
    aisPlaneXZ->SetTransformPersistence(new Graphic3d_TransformPers(Graphic3d_TMF_ZoomPers, gp_Pnt(0, 0, 0)));
    aisPlaneXZ->SetZLayer(Graphic3d_ZLayerId_Topmost);
    aisPlaneXZ->SetDisplayMode(0);
    m_context->Display(aisPlaneXZ, Standard_False);

    Handle(Geom_Plane) planeYZ = new Geom_Plane(gp_Pln(gp::YOZ()));
    Handle(AIS_Plane) aisPlaneYZ = new AIS_Plane(planeYZ);
    aisPlaneYZ->SetTransformPersistence(new Graphic3d_TransformPers(Graphic3d_TMF_ZoomPers, gp_Pnt(0, 0, 0)));
    aisPlaneYZ->SetZLayer(Graphic3d_ZLayerId_Topmost);
    aisPlaneYZ->SetDisplayMode(0);
    m_context->Display(aisPlaneYZ, Standard_False);

    /*创建中心坐标轴*/
    gp_Pnt origin(0, 0, 0);

    gp_Dir xDir(1, 0, 0);
    Handle(AIS_Axis) xAxis = new AIS_Axis(gp_Ax1(origin, xDir));
    xAxis->SetInfiniteState(Standard_False);
    xAxis->SetColor(Quantity_NOC_RED);
    xAxis->SetTransformPersistence(new Graphic3d_TransformPers(Graphic3d_TMF_ZoomPers, origin));
    xAxis->Attributes()->SetZLayer(Graphic3d_ZLayerId_Topmost);
    m_context->Display(xAxis, Standard_True);
    gp_Dir yDir(0, 1, 0);
    Handle(AIS_Axis) yAxis = new AIS_Axis(gp_Ax1(origin, yDir));
    yAxis->SetColor(Quantity_NOC_GREEN);
    yAxis->SetTransformPersistence(new Graphic3d_TransformPers(Graphic3d_TMF_ZoomPers, origin));
    yAxis->Attributes()->SetZLayer(Graphic3d_ZLayerId_Topmost);
    m_context->Display(yAxis, Standard_True);
    gp_Dir zDir(0, 0, 1);
    Handle(AIS_Axis) zAxis = new AIS_Axis(gp_Ax1(origin, zDir));
    zAxis->SetColor(Quantity_NOC_BLUE);
    zAxis->SetTransformPersistence(new Graphic3d_TransformPers(Graphic3d_TMF_ZoomPers, origin));
    zAxis->Attributes()->SetZLayer(Graphic3d_ZLayerId_Topmost);
    m_context->Display(zAxis, Standard_True);
    // 开始交互
    m_view->FitAll();
    m_view->ZFitAll();
    m_view->MustBeResized();


}


Handle(AIS_ViewCube) OccWidget::Create_AIS_ViewCube() {
    //设置视方体
    Handle(AIS_ViewCube) H_AisViewCube = new AIS_ViewCube();
    //下面是自定义每个面的文本
    H_AisViewCube->SetBoxSideLabel(V3d_Xpos, "Right");
    H_AisViewCube->SetBoxSideLabel(V3d_Ypos, "Back");
    H_AisViewCube->SetBoxSideLabel(V3d_Zpos, "Top");
    H_AisViewCube->SetBoxSideLabel(V3d_Xneg, "Left");
    H_AisViewCube->SetBoxSideLabel(V3d_Yneg, "Front");
    H_AisViewCube->SetBoxSideLabel(V3d_Zneg, "Bottom");
    H_AisViewCube->SetSize(45.0, Standard_True);
    H_AisViewCube->SetBoxColor(Quantity_NOC_WHITE); //设置视方体为白色
    H_AisViewCube->SetTransparency(0.8);
    //设置视方体每个面的字体为黑色
    H_AisViewCube->SetTextColor(Quantity_Color(Quantity_NOC_MATRABLUE));
    H_AisViewCube->SetFontHeight(18);

    //设置视方体每个面的边界线
    const Handle(Prs3d_Drawer)& drawer = H_AisViewCube->Attributes();
    drawer->SetupOwnFaceBoundaryAspect();
    drawer->SetFaceBoundaryDraw(true);
    //设置边界线的颜色为Quantity_NOC_GRAY
    drawer->FaceBoundaryAspect()->SetColor(Quantity_NameOfColor::Quantity_NOC_GREENYELLOW);
    drawer->FaceBoundaryAspect()->SetWidth(0.5);
    H_AisViewCube->SetMaterial(Graphic3d_MaterialAspect(Graphic3d_NOM_DEFAULT));

    //设置视方体基准线
    drawer->SetDatumAspect(new Prs3d_DatumAspect());
    const Handle_Prs3d_DatumAspect& datumAspect = H_AisViewCube->Attributes()->DatumAspect();
    //设置轴颜色
    datumAspect->ShadingAspect(Prs3d_DP_XAxis)->SetColor(Quantity_NOC_RED);
    datumAspect->ShadingAspect(Prs3d_DP_YAxis)->SetColor(Quantity_NOC_GREEN);
    datumAspect->ShadingAspect(Prs3d_DP_ZAxis)->SetColor(Quantity_NOC_BLUE);
    //设置X,Y,Z文本颜色
    datumAspect->TextAspect(Prs3d_DP_XAxis)->SetColor(Quantity_NOC_RED);
    datumAspect->TextAspect(Prs3d_DP_YAxis)->SetColor(Quantity_NOC_GREEN);
    datumAspect->TextAspect(Prs3d_DP_ZAxis)->SetColor(Quantity_NOC_BLUE);
    /*设置在右上角*/
    H_AisViewCube->SetTransformPersistence(
        new Graphic3d_TransformPers(
            Graphic3d_TMF_TriedronPers,
            Aspect_TOTP_RIGHT_UPPER,
            Graphic3d_Vec2i(100, 100)));


    return H_AisViewCube;

}


void OccWidget::paintEvent(QPaintEvent*) {
    m_view->Redraw();
    QPainter* paint = new QPainter;
    paint->begin(this);
    paint->setPen(QPen(Qt::blue, 4, Qt::DashLine));//设置画笔形式 
    paint->setBrush(QBrush(Qt::red, Qt::SolidPattern));//设置画刷形式 
    paint->drawRect(20, 20, 160, 160);
    paint->end();
}

void OccWidget::resizeEvent(QResizeEvent*) {
    if (!m_view.IsNull()) {
        m_view->MustBeResized();
    }
}
QPaintEngine* OccWidget::paintEngine() const {
    return 0;

}
OccWidget::~OccWidget()
{

}

void OccWidget::wheelEvent(QWheelEvent* event) {
    m_view->StartZoomAtPoint(event->position().x(), event->position().y());
    m_view->ZoomAtPoint(0, 0, event->angleDelta().y() * 0.06, 0);
}



void OccWidget::mousePressEvent(QMouseEvent* event) {
    /*设置选择框的开始点*/
    select_start_x = event->pos().x();
    select_start_y = event->pos().y();
    /*消息处理*/
    if (event->buttons() & Qt::RightButton) {
        m_mode = Panning;
        m_x = event->pos().x();
        m_y = event->pos().y();
    }
    else if (event->buttons() & Qt::MidButton) {
        if (_VIEW_MODE == VIEW_3D) {
            m_mode = Rotation;
            m_view->StartRotation(event->pos().x(), event->pos().y());
        }
    }
    else if (event->buttons() & Qt::LeftButton) {
        m_mode = Selection;
        select_start_x = event->pos().x();
        select_start_y = event->pos().y();
        /*查看选中的模型*/
        AIS_StatusOfPick sta = m_context->Select(false);
        m_context->UpdateSelected(true);
    }
    /*绘制选择矩形框*/


}


void OccWidget::mouseMoveEvent(QMouseEvent* event) {
    Q_UNUSED(event);
    m_context->MoveTo(event->pos().x(), event->pos().y(), m_view, Standard_True);
    switch (m_mode) {
    case OccWidget::Nothings:
        break;
    case OccWidget::Panning:
        m_view->Pan(event->pos().x() - m_x, m_y - event->pos().y());
        m_x = event->pos().x();
        m_y = event->pos().y();
        break;
    case OccWidget::Rotation:
        m_view->Rotation(event->pos().x(), event->pos().y());
        break;
    case OccWidget::Selection:
        m_context->Select(select_start_x, select_start_y, event->pos().x(), event->pos().y(), m_view, Standard_True);
        // TODO:  在此添加命令处理程序代码
        m_view->Window()->Size(view_width, view_height);//获取窗体尺寸
        //设置矩形边界
        m_selection_rect->SetRectangle(select_start_x, view_height - select_start_y, event->pos().x(), view_height - event->pos().y());
        //更新或显示选择框
        if (m_context->IsDisplayed(m_selection_rect))
            m_context->Redisplay(m_selection_rect, Standard_True);
        else
            m_context->Display(m_selection_rect, Standard_True);

        break;
    default:
        break;
    }
}


void OccWidget::setOccViewMode(OCCViewMode view_mode) {
    _VIEW_MODE = view_mode;
    Standard_Integer aWidth = 0, aHeight = 0, anOffset = 0;
    Handle(Graphic3d_AspectMarker3d) aGridAspect = new Graphic3d_AspectMarker3d(Aspect_TOM_RING1, Quantity_NOC_WHITE, 2);
    switch (view_mode) {
    case OccWidget::VIEW_2D:
        this->SetAllowRotation(Standard_False);
        m_viewer->SetGridEcho(aGridAspect);
        m_view->Window()->Size(aWidth, aHeight);
        m_viewer->SetRectangularGridGraphicValues(aWidth, aHeight, anOffset);
        m_viewer->ActivateGrid(Aspect_GT_Rectangular, Aspect_GDM_Lines);
        m_view->SetProj(V3d_Zpos);
        m_viewer->Redraw();
        break;
    case OccWidget::VIEW_3D:
        SetAllowRotation(Standard_True);
        m_viewer->DeactivateGrid();
        m_view->SetBackgroundColor(Quantity_Color(0.0, 0.2, 0.0, Quantity_TOC_RGB));
        m_view->SetProj(V3d_XposYposZpos);
        break;
    default:
        break;
    }

}



void OccWidget::mouseReleaseEvent(QMouseEvent* event) {
    m_mode = Nothings;
    /*如果松开左键-取消矩形框*/
    if (event->button() & Qt::LeftButton && m_context->IsDisplayed(m_selection_rect)) {
        m_context->Remove(m_selection_rect, Standard_True);
        m_view->Update();
    }

    //for (m_context->InitSelected(); m_context->MoreSelected(); m_context->NextSelected()){
    //    //选取的asi显示对象
    //    Handle(AIS_InteractiveObject)  aisObj = m_context->SelectedInteractive();
    //    //选的具体对象边 线 面
    //    TopoDS_Shape aShape = m_context->SelectedShape();
    //    if (aShape.IsNull())
    //        return;
    //    //选取的shape对象类型	
    //    std::string strType = "NULL";
    //    TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
    //    switch (aShapeType){
    //    case TopAbs_COMPOUND:
    //        strType = "TopAbs_COMPOUND";
    //        break;
    //    case TopAbs_COMPSOLID:
    //        strType = "TopAbs_COMPSOLID";
    //        break;
    //    case TopAbs_SOLID:
    //        strType = "TopAbs_SOLID";
    //        break;
    //    case TopAbs_SHELL:
    //        strType = "TopAbs_SHELL";
    //        break;
    //    case TopAbs_FACE:
    //        strType = "TopAbs_FACE";
    //        break;
    //    case TopAbs_WIRE:
    //        strType = "TopAbs_WIRE";
    //        break;
    //    case TopAbs_EDGE:
    //        strType = "TopAbs_EDGE";
    //        break;
    //    case TopAbs_VERTEX:
    //        strType = "TopAbs_VERTEX";
    //        break;
    //    case TopAbs_SHAPE:
    //        strType = "TopAbs_SHAPE";
    //        break;
    //    default:
    //        break;
    //    }

    //    //QMessageBox::information(this, tr("选取"), tr(strType.c_str()));
    //}

}

//模型切换为线框模式
void OccWidget::onButtonWire() {
    // TODO: 在此添加命令处理程序代码
    m_context->SetDisplayMode(AIS_WireFrame, Standard_True);  //设置显示模式为网状体
}


//模型切换为实体模式
void OccWidget::onButtonSolid() {
    // TODO: 在此添加命令处理程序代码
    m_context->SetDisplayMode(AIS_Shaded, Standard_True);   //设置显示模式为实体
}


//切换为模型的上部视角
void OccWidget::onButtonUp() {
    // TODO: 在此添加命令处理程序代码
    m_view->SetProj(V3d_Zpos, Standard_True);
    m_view->FitAll();
    m_view->ZFitAll();
}

//切换为模型的底部视角
void OccWidget::onButtonBottom() {
    // TODO: 在此添加命令处理程序代码
    m_view->SetProj(V3d_Zneg, Standard_True);
    m_view->FitAll();
    m_view->ZFitAll();
}

//切换为模型的左侧视角
void OccWidget::onButtonLeft() {
    // TODO: 在此添加命令处理程序代码
    m_view->SetProj(V3d_Xneg, Standard_True);
    m_view->FitAll();
    m_view->ZFitAll();

}

//切换为模型的右侧视角
void OccWidget::onButtonRight() {
    // TODO: 在此添加命令处理程序代码
    m_view->SetProj(V3d_Xpos, Standard_True);
    m_view->FitAll();
    m_view->ZFitAll();
}

//切换为模型的前面视角
void OccWidget::onButtonFront() {
    // TODO: 在此添加命令处理程序代码
    m_view->SetProj(V3d_Yneg, Standard_True);
    m_view->FitAll();
    m_view->ZFitAll();
}

//切换为模型的后面视角
void OccWidget::onButtonBack() {
    // TODO: 在此添加命令处理程序代码
    m_view->SetProj(V3d_Ypos, Standard_True);
    m_view->FitAll();
    m_view->ZFitAll();
}


//切换为模型的等轴测视角
void OccWidget::onButtonSide() {
    // TODO: 在此添加命令处理程序代码
    m_view->SetProj(V3d_XposYposZpos, Standard_True);
    m_view->FitAll();
    m_view->ZFitAll();
}

Handle(AIS_InteractiveContext) OccWidget::get_AIS_Context() {
    return m_context;
}
Handle(V3d_View) OccWidget::get_AIS_View() {
    return m_view;
}


NAMESPACE_END